#include "video_render_widget.h"
#include <QDebug>
#include <QThread>
#include <GL/wglew.h>
#include <windows.h>

// 顶点坐标和纹理坐标
static const float vertices[] = {
    // 顶点坐标     // 纹理坐标
    -1.0f, -1.0f,  0.0f, 1.0f,
     1.0f, -1.0f,  1.0f, 1.0f,
     1.0f,  1.0f,  1.0f, 0.0f,
    -1.0f,  1.0f,  0.0f, 0.0f
};

VideoRenderWidget::VideoRenderWidget(QWidget *parent)
    : QOpenGLWidget(parent)
{
    // 初始化FFmpeg
    av_register_all();
    avcodec_register_all();
    av_hwdevice_register_all();
    
    m_packet = av_packet_alloc();
    m_frame = av_frame_alloc();
}

VideoRenderWidget::~VideoRenderWidget()
{
    stopRendering();
    
    // 清理FFmpeg资源
    if (m_codecCtx) {
        avcodec_close(m_codecCtx);
        avcodec_free_context(&m_codecCtx);
    }
    if (m_fmtCtx) {
        avformat_close_input(&m_fmtCtx);
        avformat_free_context(m_fmtCtx);
    }
    av_frame_free(&m_frame);
    av_packet_free(&m_packet);
    
    // 清理D3D11资源
    if (m_d3d11Context) m_d3d11Context->Release();
    if (m_d3d11Device) m_d3d11Device->Release();
    
    // 清理OpenGL资源
    makeCurrent();
    if (m_vertexBuffer) glDeleteBuffers(1, &m_vertexBuffer);
    if (m_vertexArray) glDeleteVertexArrays(1, &m_vertexArray);
    if (m_texture) glDeleteTextures(1, &m_texture);
    delete m_shaderProgram;
    doneCurrent();
}

bool VideoRenderWidget::initD3D11()
{
    UINT createDeviceFlags = 0;
    D3D_FEATURE_LEVEL featureLevel;
    const D3D_FEATURE_LEVEL featureLevelArray[2] = {
        D3D_FEATURE_LEVEL_11_0,
        D3D_FEATURE_LEVEL_10_0,
    };

    HRESULT hr = D3D11CreateDevice(
        nullptr,                   // 使用默认适配器
        D3D_DRIVER_TYPE_HARDWARE,  // 硬件加速
        nullptr,                   // 软件驱动
        createDeviceFlags,
        featureLevelArray,
        2,
        D3D11_SDK_VERSION,
        &m_d3d11Device,
        &featureLevel,
        &m_d3d11Context
    );

    return SUCCEEDED(hr);
}

bool VideoRenderWidget::checkWglExtensions()
{
    // 初始化WGL
    if (wglewInit() != GLEW_OK) {
        qCritical() << "Failed to initialize WGL";
        return false;
    }

    // 检查WGL_NV_DX_interop扩展
    if (!wglewIsSupported("WGL_NV_DX_interop")) {
        qCritical() << "WGL_NV_DX_interop extension not supported";
        return false;
    }
    
    // 打开WGL设备
    m_wglDevice = wglDXOpenDeviceNV((void*)m_d3d11Device);
    if (!m_wglDevice) {
        qCritical() << "Could not open WGL device";
        return false;
    }
    
    return true;
}

bool VideoRenderWidget::initializeDecoder(const QString &inputFile)
{
    // 初始化D3D11
    if (!initD3D11()) {
        qCritical() << "Failed to initialize D3D11";
        return false;
    }

    // 打开输入文件
    m_fmtCtx = avformat_alloc_context();
    if (avformat_open_input(&m_fmtCtx, inputFile.toUtf8().constData(), nullptr, nullptr) != 0) {
        qCritical() << "Could not open input file:" << inputFile;
        return false;
    }

    // 查找流信息
    if (avformat_find_stream_info(m_fmtCtx, nullptr) < 0) {
        qCritical() << "Could not find stream information";
        return false;
    }

    // 查找视频流
    m_videoStreamIdx = av_find_best_stream(m_fmtCtx, AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0);
    if (m_videoStreamIdx < 0) {
        qCritical() << "Could not find video stream";
        return false;
    }

    // 查找硬件解码器 (D3D11VA)
    const AVCodec* codec = avcodec_find_decoder_by_name("h264_qsv");
    if (!codec) {
        qCritical() << "Codec not found";
        return false;
    }

    // 创建解码器上下文
    m_codecCtx = avcodec_alloc_context3(codec);
    if (!m_codecCtx) {
        qCritical() << "Could not allocate codec context";
        return false;
    }

    // 复制流参数
    if (avcodec_parameters_to_context(m_codecCtx, m_fmtCtx->streams[m_videoStreamIdx]->codecpar) < 0) {
        qCritical() << "Could not copy codec parameters";
        return false;
    }

    // 设置硬件解码上下文
    AVBufferRef* hwDeviceCtx = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_D3D11VA);
    if (!hwDeviceCtx) {
        qCritical() << "Could not allocate HW device context";
        return false;
    }

    // 初始化硬件设备上下文
    if (av_hwdevice_ctx_init(hwDeviceCtx) < 0) {
        qCritical() << "Could not initialize HW device context";
        av_buffer_unref(&hwDeviceCtx);
        return false;
    }
    m_codecCtx->hw_device_ctx = av_buffer_ref(hwDeviceCtx);

    // 打开解码器
    if (avcodec_open2(m_codecCtx, codec, nullptr) < 0) {
        qCritical() << "Could not open codec";
        return false;
    }

    return true;
}

void VideoRenderWidget::startRendering()
{
    m_rendering = true;
    update();
}

void VideoRenderWidget::stopRendering()
{
    m_rendering = false;
}

void VideoRenderWidget::initializeGL()
{
    initializeOpenGLFunctions();
    
    // 检查WGL扩展
    if (!checkWglExtensions()) {
        return;
    }

    // 编译着色器
    m_shaderProgram = new QOpenGLShaderProgram();
    m_shaderProgram->addShaderFromSourceCode(QOpenGLShader::Vertex,
        "#version 330 core\n"
        "layout (location = 0) in vec2 aPos;\n"
        "layout (location = 1) in vec2 aTexCoord;\n"
        "out vec2 TexCoord;\n"
        "void main()\n"
        "{\n"
        "   gl_Position = vec4(aPos, 0.0, 1.0);\n"
        "   TexCoord = aTexCoord;\n"
        "}\n");
    
    m_shaderProgram->addShaderFromSourceCode(QOpenGLShader::Fragment,
        "#version 330 core\n"
        "in vec2 TexCoord;\n"
        "out vec4 FragColor;\n"
        "uniform sampler2D ourTexture;\n"
        "void main()\n"
        "{\n"
        "   FragColor = texture(ourTexture, TexCoord);\n"
        "}\n");
    
    if (!m_shaderProgram->link()) {
        qCritical() << "Shader program link error:" << m_shaderProgram->log();
        return;
    }

    // 设置顶点缓冲
    glGenVertexArrays(1, &m_vertexArray);
    glGenBuffers(1, &m_vertexBuffer);
    
    glBindVertexArray(m_vertexArray);
    glBindBuffer(GL_ARRAY_BUFFER, m_vertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    
    // 顶点属性
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));
    glEnableVertexAttribArray(1);
    
    // 初始化纹理
    glGenTextures(1, &m_texture);
    glBindTexture(GL_TEXTURE_2D, m_texture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    
    glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
}

void VideoRenderWidget::resizeGL(int w, int h)
{
    glViewport(0, 0, w, h);
}

void VideoRenderWidget::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT);

    if (!m_rendering || !m_codecCtx) {
        return;
    }

    // 读取并解码帧
    while (m_rendering && av_read_frame(m_fmtCtx, m_packet) >= 0) {
        if (m_packet->stream_index == m_videoStreamIdx) {
            if (avcodec_send_packet(m_codecCtx, m_packet) >= 0) {
                while (avcodec_receive_frame(m_codecCtx, m_frame) >= 0) {
                    // 渲染帧
                    renderFrame(m_frame);
                    av_frame_unref(m_frame);
                    
                    // 只渲染一帧就退出，等待下一次paintGL调用
                    av_packet_unref(m_packet);
                    return;
                }
            }
        }
        av_packet_unref(m_packet);
    }
    
    // 如果所有帧都处理完了，停止渲染
    m_rendering = false;
}

void VideoRenderWidget::renderFrame(AVFrame* frame)
{
    if (!frame->hw_frames_ctx) {
        qCritical() << "No hardware frame context";
        return;
    }

    // 获取D3D11纹理
    AVHWFramesContext* hwFramesCtx = (AVHWFramesContext*)frame->hw_frames_ctx->data;
    ID3D11Texture2D* d3d11Texture = (ID3D11Texture2D*)hwFramesCtx->hwctx->d3d11.texture;
    if (!d3d11Texture) {
        qCritical() << "Could not get D3D11 texture";
        return;
    }

    // 获取共享句柄
    IDXGIResource* dxgiResource = nullptr;
    if (d3d11Texture->QueryInterface(__uuidof(IDXGIResource), (void**)&dxgiResource) != S_OK) {
        qCritical() << "Could not get DXGI resource";
        return;
    }

    HANDLE sharedHandle = nullptr;
    dxgiResource->GetSharedHandle(&sharedHandle);
    dxgiResource->Release();

    if (!sharedHandle) {
        qCritical() << "Could not get shared handle";
        return;
    }

    // 注册D3D11纹理到OpenGL
    HANDLE wglObject = wglDXRegisterObjectNV(
        m_wglDevice,
        sharedHandle,
        m_texture,
        GL_TEXTURE_2D,
        WGL_ACCESS_READ_ONLY_NV
    );

    if (!wglObject) {
        qCritical() << "Could not register WGL object";
        return;
    }

    // 锁定纹理用于OpenGL访问
    wglDXLockObjectsNV(m_wglDevice, 1, &wglObject);

    // 绘制纹理
    m_shaderProgram->bind();
    glBindVertexArray(m_vertexArray);
    glBindTexture(GL_TEXTURE_2D, m_texture);
    glDrawArrays(GL_QUADS, 0, 4);

    // 解锁并清理
    wglDXUnlockObjectsNV(m_wglDevice, 1, &wglObject);
    wglDXUnregisterObjectNV(m_wglDevice, wglObject);
}
